# coding: utf-8
import re
from pathlib import Path
from typing import Any

from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QListWidgetItem, QHBoxLayout, QDialog, QFileDialog
from qfluentwidgets import BodyLabel, setFont, PushButton, ComboBox, FluentIcon, CompactSpinBox, LineEdit, InfoBar

from common import FakerUtils, SingleIcon, OfficeIcon, FileTypeIcon, FakerMethod
from components import ProviderCard, DropListWidget, ThreadObjectBase
from .add_order_interface import AddOrderDialog


class BatchInterface(ThreadObjectBase, QWidget):
    def __init__(self, parent: QWidget = None):
        super().__init__(parent)
        self.verticalLayout = QVBoxLayout(self)
        self.titleLabel = BodyLabel('批量指令列表', self)
        self.horizontalLayout = QHBoxLayout()
        self.saveEdit = LineEdit(self)
        self.fileBtn = PushButton(FluentIcon.SAVE, '选择保存文件', self)
        self.countSpinBox = CompactSpinBox(self)
        self.typeComboBox = ComboBox(self)
        self.addBtn = PushButton(FluentIcon.ADD, '添加指令', self)
        self.generateBtn = PushButton(FluentIcon.PLAY, '生成数据', self)
        self.listWidget = DropListWidget(self)
        self.fakerUtils = FakerUtils()

        self.__initWidgets()
        self.connectSignals()
        self.init_providers()

    def __initWidgets(self):
        self.setObjectName('BatchInterface')
        setFont(self.titleLabel, 26)
        self.setToolTipTitle('数据生成')
        self.setToolTipContent('正在生成数据，请稍候...')

        self.countSpinBox.setRange(1, 10000000)
        self.typeComboBox.setFixedWidth(150)
        self.typeComboBox.addItem('Excel')
        self.typeComboBox.addItem('CSV')
        self.typeComboBox.addItem('JSON')
        self.typeComboBox.addItem('YAML')
        self.saveEdit.setReadOnly(True)

        self.verticalLayout.setContentsMargins(36, 36, 36, 10)
        self.verticalLayout.addWidget(self.titleLabel)
        self.verticalLayout.addSpacing(20)
        self.horizontalLayout.addWidget(self.saveEdit)
        self.horizontalLayout.addWidget(self.fileBtn, 0, Qt.AlignmentFlag.AlignRight)
        self.horizontalLayout.addWidget(self.typeComboBox)
        self.horizontalLayout.addWidget(self.countSpinBox)
        self.horizontalLayout.addWidget(self.addBtn)
        self.horizontalLayout.addWidget(self.generateBtn)
        self.verticalLayout.addLayout(self.horizontalLayout)
        self.verticalLayout.addWidget(self.listWidget)

    def connectSignals(self):
        self.addBtn.clicked.connect(self.add_item)
        self.generateBtn.clicked.connect(self.generate_data)
        self.fileBtn.clicked.connect(self.select_file)
        self.typeComboBox.currentTextChanged.connect(self.update_file_type)

    def update_file_type(self, text: str):
        save_path = self.saveEdit.text()
        if not save_path:
            return
        path = Path(save_path)

        if text == 'Excel':
            path = path.with_suffix('.xlsx')
        elif text == 'CSV':
            path = path.with_suffix('.csv')
        elif text == 'JSON':
            path = path.with_suffix('.json')
        elif text == 'YAML':
            path = path.with_suffix('.yaml')
        self.saveEdit.setText(path.as_posix())

    def select_file(self):
        file_path, tp = QFileDialog.getSaveFileName(self, '选择保存文件', '',
                                                    'Excel Files (*.xlsx);;CSV Files (*.csv);;JSON Files (*.json);;YAML Files (*.yaml)')
        if file_path:
            self.saveEdit.setText(file_path)
        if 'json' in tp.lower():
            self.typeComboBox.setCurrentIndex(2)
        elif 'yaml' in tp.lower():
            self.typeComboBox.setCurrentIndex(3)
        elif 'csv' in tp.lower():
            self.typeComboBox.setCurrentIndex(1)
        elif 'xlsx' in tp.lower():
            self.typeComboBox.setCurrentIndex(0)

    def init_providers(self):
        provider: dict
        for provider in self.fakerUtils.get_providers():
            self.addItem(provider)

    def addItem(self, data: dict):
        item = QListWidgetItem(self.listWidget)
        card = ProviderCard(SingleIcon.FALSE, data['name'], self)
        card.setProperty('data', data)

        item.setSizeHint(card.sizeHint())
        self.listWidget.addItem(item)
        self.listWidget.setItemWidget(item, card)

        card.removed.connect(lambda cd, it=item: self.listWidget.takeItem(self.listWidget.row(it)))
        card.edited.connect(self.edit_item)

    def add_item(self):
        dialog = AddOrderDialog(self)
        if dialog.exec():
            data = dialog.get_data()
            self.addItem(data)

    def edit_item(self, card: ProviderCard):
        dialog = AddOrderDialog(self)
        dialog.setTitle('编辑指令')
        dialog.setParams(card.property('data'))
        if dialog.exec():
            data = dialog.get_data()
            card.setProperty('data', data)
            card.setText(data['name'])

    def generate_data(self):
        datas = []
        for i in range(self.listWidget.count()):
            item = self.listWidget.item(i)
            card = self.listWidget.itemWidget(item)
            data = card.property('data')
            datas.append(data)
        count = self.countSpinBox.value()
        tp = self.typeComboBox.currentText()
        file_path = self.saveEdit.text()
        if not file_path:
            return
        kwargs = {
            'methods': [data['method'] for data in datas],
            'file_path': file_path,
            'columns': [data['name'] for data in datas],
            'count': count,
        }
        if tp == 'Excel':
            self.load(self.fakerUtils.generate_data_to_excel, **kwargs)
        elif tp == 'CSV':
            self.load(self.fakerUtils.generate_data_to_csv, **kwargs)
        elif tp == 'JSON':
            self.load(self.fakerUtils.generate_data_to_json, **kwargs)
        elif tp == 'YAML':
            self.load(self.fakerUtils.generate_data_to_yaml, **kwargs)

    def onFuncSuccess(self, result: Any):
        InfoBar.success('', '数据生成成功', duration=2000, parent=self)
